package my.threading;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

public class SimpleThread
{
	LinkedList<Long> things;
	AtomicLong count = new AtomicLong();
	List<Thread> threads = new ArrayList<Thread>();
	
	public static void main(String [] args) throws InterruptedException
	{		
		//ReentrantLock lock;
		SimpleThread t = new SimpleThread();
		t.run();
	}
	
	public void run() throws InterruptedException
	{
		things = new LinkedList<Long>();
		Collections.addAll(things, new Long [] {new Long(1), new Long(3), new Long(2), new Long(7), new Long(8), new Long(13), new Long(9)});		
		
		for(int i =0; i <100; i++)
		{
			Thread t = new Thread(new Worker(),"T" + i);
			t.start();
			threads.add(t);
		}
				
		while (count.get() < 100)
		{
			Thread.sleep(1000);
		}
		
		System.out.println("Work done interrupting");
		for (Thread t : threads)
		{
			t.interrupt();
		}
		Thread.sleep(50);
		System.out.println("Work done.");
	}
	
	class Worker implements Runnable
	{
		boolean alive = true;
		public void run()
		{
			while (alive)				
			{
				
				Long thing;
				try
				{
					thing = getThing();
					System.out.println("Thread: " + Thread.currentThread().getName() + " Thing: " + thing);
					Thread.sleep(1000);
					returnThing(thing);
					Thread.sleep(50);
					
				} catch (InterruptedException e)
				{
					System.out.println("Thread: " + Thread.currentThread().getName() + " has been interrupted and will exit.");
					break;
				}			
			}
		}		
	}
	
	private Long getThing() throws InterruptedException
	{
		synchronized (things)
		{
			while (things.size() == 0)
			{
				things.wait();
			}
			return things.remove();
		}
	}
	
	private void returnThing(Long thing) throws InterruptedException
	{
		synchronized (things)
		{
			things.add(thing);
			things.notifyAll();
			count.incrementAndGet();
		}
	}
	
}
